# -*- coding: utf-8 -*-
# created on 2016/10/24

from sympy import Interval, Symbol, sympify, zoo, oo
from mathsolver.functions.base.base import BaseFunction
from mathsolver.functions.base.objects import (BaseSet, BaseInter, BaseEqs, BaseEq, BaseSymbolValue, BaseVariable,
                                               BaseVariables)
from mathsolver.functions.hanshu.helper import check_func, cal_canshu_from_expr
from mathsolver.functions.mathematica.mathematicaSolve import MathematicaSolve


class JiOuDingYiYuQiuCan(BaseFunction):
    def solver(self, *args):
        """
        已知函数奇偶性及含参定义域，求参数
        :param args: [0] - Interval 含参定义域
        :return: BaseEq/BaseEqs
        """
        inter = args[0]
        if isinstance(inter, BaseSet):
            sum_ = 0
            symbollist = ''
            if 'set' in inter.value['conditions'][0]:
                for num in inter.value['conditions'][0]['set']:
                    if isinstance(num, str):
                        if '(' in num:
                            num = num.replace('(', '').replace(')', '')
                        try:
                            num = int(num)
                            sum_ += num
                        except ValueError:
                            symbollist += num + '+'
                    else:
                        if isinstance(num, int):
                            sum_ += num
                        elif isinstance(num, Symbol):
                            symbollist += num.name + '+'
                eq = BaseEq([symbollist[:-1], -sum_])
                self.steps.append(["∵ 定义域关于原点对称", "∴ 等式成立：{}".format(eq.printing())])
                self.output.append(eq)
        elif isinstance(inter, BaseInter):
            inter = inter.interval
            eqlist = []
            if isinstance(inter.args[0], Interval):
                for i in range(len(inter.args)):
                    if inter.args[i].args[0].is_Symbol:
                        sym = inter.args[i].args[0].name
                        valcont = inter.args[-1 - i].args[1]
                        if valcont.is_Symbol:
                            eqlist.append([sym, '-' + valcont.name])
                        elif valcont.is_Number:
                            eqlist.append([sym, -valcont.p])
                    if inter.args[i].args[1].is_Symbol:
                        sym = inter.args[i].args[1].name
                        valcont = inter.args[-1 - i].args[0]
                        if valcont.is_Symbol:
                            eqlist.append([sym, '-' + valcont.name])
                        elif valcont.is_Number:
                            eqlist.append([sym, -valcont.p])
                if len(inter.args) % 2 == 1:
                    if inter.args[len(inter.args) // 2].args[0].is_Symbol and not inter.args[len(inter.args) // 2].args[1].is_Symbol:
                        eqlist.append([inter[len(inter.args) // 2].args[0], -inter[len(inter.args) // 2].args[1]])
                    elif not inter.args[len(inter.args) // 2].args[0].is_Symbol and \
                            inter.args[len(inter.args) // 2].args[1].is_Symbol:
                        eqlist.append([inter[len(inter.args) // 2].args[1], -inter[len(inter.args) // 2].args[0]])
                if len(eqlist) == 1:
                    self.steps.append(["∵ 定义域关于原点对称", "∴ 解得参数："])
                    if isinstance(eqlist[0][0], Symbol):
                        eq = BaseSymbolValue({eqlist[0][0]: eqlist[0][1]})
                    elif isinstance(eqlist[0][1], Symbol):
                        eq = BaseSymbolValue({eqlist[0][1]: eqlist[0][0]})
                    self.steps.append([eq.printing(), ""])
                    self.output.append(eq)
                else:
                    self.steps.append(["∵ 定义域关于原点对称", "∴ 解得参数："])
                    for item in eqlist:
                        eq = BaseSymbolValue({item[0]: item[1]})
                        self.steps.append([eq.printing(), ""])
                        self.output.append(eq)
                    self.output.append(BaseEqs(eqlist))
            else:
                self.steps.append(["∵ 定义域关于原点对称", "∴ 解得参数："])
                if isinstance(inter.args[0], Symbol):
                    eq = BaseSymbolValue({inter.args[0]: -inter.args[1]})
                elif isinstance(inter.args[1], Symbol):
                    eq = BaseSymbolValue({inter.args[1]: -inter.args[0]})
                self.steps.append([eq.printing(), ""])
                self.output.append(eq)
        self.label.add("根据函数奇偶性求参数")
        return self


class JiOuQiuCan2(BaseFunction):
    """根据含参表达式的奇偶性求解参数值 - 2个参数"""

    @staticmethod
    def _is_bad_expr(expr):
        return "I" in str(expr) or expr.has(oo) or expr.has(zoo)

    def solver(self, *args):
        func = check_func(args[0])
        expr, var = func.expression, func.var
        symbs = expr.free_symbols
        canshus = symbs - {var}
        test_value = [sympify('1/2'), sympify('1/5'), 0, 1, sympify('3/5'), 5, 11]
        fuhao = -1 if '奇' in args[1] else 1

        for i in range(len(test_value) - 3):
            p1 = test_value[i]
            expr1, expr2 = expr.subs(var, p1), fuhao * expr.subs(var, -p1)

            if self._is_bad_expr(expr1) or self._is_bad_expr(expr2):
                continue

            for j in range(i + 1, len(test_value) - 1):
                p2 = test_value[j]
                expr3, expr4 = expr.subs(var, p2), fuhao * expr.subs(var, -p2)
                if self._is_bad_expr(expr3) or self._is_bad_expr(expr4):
                    continue

                for k in range(j+1, len(test_value) - 2):
                    p3 = test_value[k]
                    expr5, expr6 = expr.subs(var, p3), fuhao * expr.subs(var, -p3)

                    eqs = BaseEqs([[expr1, expr2], [expr3, expr4], [expr5, expr6]])
                    # 用 Mathematica 解等式
                    try:
                        eq_solver = MathematicaSolve().solver(eqs, BaseVariables(canshus)).output
                    except Exception:
                        continue
                    else:
                        self.steps.append(["", "将 x = %s， x = %s，和 x = %s 分别代入方程" % (p1, p2, p3)])
                        self.output = eq_solver
                        self.steps.append(["", "解方程组得 %s" % eq_solver[0].printing()])
                        self.label.add("根据函数奇偶性求参数")
                        return self

        raise RuntimeError("cannot solve problem")


class JiOuQiuCan(BaseFunction):
    """根据含参表达式的奇偶性求解参数值"""

    def solver(self, *args):
        func = check_func(args[0])
        expr, var = func.expression, func.var
        symbs = expr.free_symbols
        if len(symbs) > 2:
            return JiOuQiuCan2().solver(*args)
        else:
            canshu = cal_canshu_from_expr(expr)

        test_value = [sympify('1/2'), sympify('1/5'), sympify('3/5'), 0, 1, 5, 11]
        fuhao = -1 if '奇' in args[1] else 1

        for point in test_value:
            result = BaseEq([expr.subs(var, point), fuhao * expr.subs(var, -point)])

            # 用 Mathematica 解等式
            try:
                eq_solver = MathematicaSolve().solver(result, BaseVariable([canshu])).output
            except Exception:
                continue
            else:
                if not eq_solver[0].value.get(canshu):
                    continue

                self.steps.append(["", "令 x = %s, 根据函数奇偶性得：%s" % (point, result.printing())])
                self.output = eq_solver
                self.steps.append(["", "解得 %s" % eq_solver[0].printing()])
                self.label.add("根据函数奇偶性求参数")
                return self

        raise RuntimeError("cannot solve problem")


if __name__ == '__main__':
    pass
